package company.maestro;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.Date;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

public class StudentDBAdapter 
{
  private static final String DATABASE_NAME 	= "maestro.db";
  private static final String DATABASE_TABLE 	= "students";
  private static final int DATABASE_VERSION 	= 15;
 
  // Column names
  public static final String KEY_ID 					= "_id";
  public static final String KEY_CLASS_ID  			= "class_id";
  public static final String KEY_STUDENT_FIRST_NAME 	= "student_first_name";
  public static final String KEY_STUDENT_LAST_NAME 	= "student_last_name";
  public static final String KEY_CREATION_DATE 		= "creation_date";
  public static final String KEY_GUARDIAN_NAME 		= "guardian_name";
  public static final String KEY_GUARDIAN_PHONE 		= "guardian_phone";
  public static final String KEY_GUARDIAN_EMAIL 		= "guardian_email";
  
  private File 					contextDirectory;
  private SQLiteDatabase 		db;
  private static Context 		context;
  private studentDBOpenHelper 	dbHelper;
  
  // Used for the singleton pattern
  private static StudentDBAdapter singleton = null;
  
  public static StudentDBAdapter getInstance(Context _context)
  {
	  if ( singleton == null )
	  {
		  singleton = new StudentDBAdapter(_context);
	  }
	  return singleton;
  }

  private StudentDBAdapter(Context _context) 
  {
    this.context = _context;
    dbHelper = new studentDBOpenHelper(context, DATABASE_NAME, 
                                    null, DATABASE_VERSION);
  }
  
  
  public void close() 
  {
    db.close();
  }
  
  
  public void open() throws SQLiteException 
  {  
    try 
    {
      db = dbHelper.getWritableDatabase();
    } 
    catch (SQLiteException ex) 
    {
      db = dbHelper.getReadableDatabase();
    }
  }  
  
  
  /**
   * Used to save a picture of a student
   * @param studentId The id of the student the image is for
   * @param bitmap The image to be saved
   * @return If the save was successful or not
   */
  public boolean saveStudentImage(long studentId, Bitmap bitmap)
  {
	  File directory = context.getFilesDir();
	  try
	  {
		  ByteArrayOutputStream bytes = new ByteArrayOutputStream();
		 
		  bitmap.compress(Bitmap.CompressFormat.JPEG, 40, bytes);
		  
		  String fileName = "STUDENT_ID_" + studentId + ".jpg";
		  
		  File f = new File(directory.toString()
		                          + File.separator + fileName);
		  f.createNewFile();
		  //write the bytes in file
		  FileOutputStream fo = new FileOutputStream(f);
		  
		  fo.write(bytes.toByteArray());
		  fo.close();
		  
		  return true;
	  }
	  catch (Exception e)
	  {
		  CharSequence message = "Error occured";
		  Log.e("Saving Picture", "Error saving student image");
		  return false;
	  }
  }
  
  
  /**
   * Used to retrieve a picture for a student
   * @param studentId The id of the student to get the image for
   * @return The picture of the student
   * @throws FileNotFoundException
   */
  public static Bitmap getImageForStudent(long studentId) throws FileNotFoundException
  {
	  String fileName = "STUDENT_ID_" + studentId + ".jpg";
	  String fullFileName = context.getFilesDir()
      		+ File.separator + fileName;
	  FileInputStream in = new FileInputStream(fullFileName);
      BitmapFactory.Options options = new BitmapFactory.Options();
      options.inSampleSize = 3; //Downsample 10x
      Bitmap userImage = BitmapFactory.decodeStream(in, null, options);
      
      return userImage;
  }
  
  
  /**
   * Insert a student into the database
   * @param _student The student to be inserted
   * @return Id of the newly inserted student
   */
  public long insertStudent(Student _student) 
  {
    // Create a new row of values to insert.
    ContentValues newTaskValues = new ContentValues();
    
    // Assign values for each row.
    newTaskValues.put(KEY_CLASS_ID, _student.getClassId());
    newTaskValues.put(KEY_STUDENT_FIRST_NAME, _student.getFirstName());
    newTaskValues.put(KEY_STUDENT_LAST_NAME, _student.getLastName());
    newTaskValues.put(KEY_CREATION_DATE, _student.getCreated().getTime());
    newTaskValues.put(KEY_GUARDIAN_NAME, _student.getGuardianName());
    newTaskValues.put(KEY_GUARDIAN_PHONE, _student.getGuardianPhoneNumber());
    newTaskValues.put(KEY_GUARDIAN_EMAIL, _student.getGuardianEmail());
    
    // Insert the row.
    return db.insert(DATABASE_TABLE, null, newTaskValues);
  }

  
  /**
   * 
   * Remove a student from the database
   * @param _rowIndex The id of the student to be removed
   * @return Whether the remove was successful or not
   */
  public boolean removeStudent(long _rowIndex) 
  {
    return db.delete(DATABASE_TABLE, KEY_ID + "=" + _rowIndex, null) > 0;
  }

  
  /**
   * TODO: this function needs to be changed
   */
  public boolean updateStudent(long _rowIndex, String _task) 
  {
    ContentValues newValue = new ContentValues();
    newValue.put(KEY_STUDENT_FIRST_NAME, _task);
    return db.update(DATABASE_TABLE, newValue, KEY_ID + "=" + _rowIndex, null) > 0;
  }
  
  
  /**
   * Retrieve all students from the database
   * @return Cursor to the rowset of all students
   */
  public Cursor getAllStudentsCursor() 
  {
	String orderByString = KEY_STUDENT_LAST_NAME;  
	
    return db.query(DATABASE_TABLE, 
                    new String[] { KEY_ID, KEY_STUDENT_FIRST_NAME, 
    					KEY_STUDENT_LAST_NAME, KEY_GUARDIAN_NAME, KEY_GUARDIAN_PHONE, 
    					KEY_GUARDIAN_EMAIL, KEY_CREATION_DATE }, 
                    null, null, null, null, orderByString + " desc");
  }
  
  
  /**
   * Retrieve all students in a given class
   * @param classId Id of the class
   * @return Cursor to the rowset of Students in this class
   */
  public Cursor getAllStudentsForClass(long classId)
  {
	  String orderByString = KEY_STUDENT_LAST_NAME;  
		
	  return db.query(DATABASE_TABLE, 
	                new String[] { KEY_ID, KEY_CLASS_ID, KEY_STUDENT_FIRST_NAME, 
			  			KEY_STUDENT_LAST_NAME, KEY_GUARDIAN_NAME, KEY_GUARDIAN_PHONE, 
			  			KEY_GUARDIAN_EMAIL, KEY_CREATION_DATE }, 
			  			KEY_CLASS_ID + "=" + classId, null, null, null, 
			  			orderByString + " desc");
  }
  

  public Cursor setCursorToStudent(long _rowIndex) throws SQLException 
  {
    Cursor result = db.query(true, DATABASE_TABLE, 
	                           new String[] {KEY_ID, KEY_STUDENT_FIRST_NAME},
                             KEY_ID + "=" + _rowIndex, null, null, null, 
                             null, null);
    if ((result.getCount() == 0) || !result.moveToFirst()) 
    {
      throw new SQLException("No to do items found for row: " + _rowIndex);
    }
    return result;
  }
  
  
  /**
   * Get a selected student
   * @param _rowIndex Student id
   * @return The student with the given id
   * @throws SQLException
   */
  public Student getStudent(long _rowIndex) throws SQLException 
  {
    Cursor cursor = db.query(true, DATABASE_TABLE, 
                             new String[] {KEY_ID, KEY_STUDENT_FIRST_NAME},
                             KEY_ID + "=" + _rowIndex, null, null, null, 
                             null, null);
    if ((cursor.getCount() == 0) || !cursor.moveToFirst()) 
    {
      throw new SQLException("No student found for row: " + _rowIndex);
    }

    long id = cursor.getLong(cursor.getColumnIndex(KEY_ID));
    String firstName = cursor.getString(cursor.getColumnIndex(KEY_STUDENT_FIRST_NAME));
    String lastName = cursor.getString(cursor.getColumnIndex(KEY_STUDENT_LAST_NAME));
    String guardianName = cursor.getString(cursor.getColumnIndex(KEY_GUARDIAN_NAME));
    String guardianPhone = cursor.getString(cursor.getColumnIndex(KEY_GUARDIAN_PHONE));
    String guardianEmail = cursor.getString(cursor.getColumnIndex(KEY_GUARDIAN_EMAIL));
    long created = cursor.getLong(cursor.getColumnIndex(KEY_CREATION_DATE));
		  
    Student result = new Student(id, firstName, lastName, guardianName, guardianPhone, guardianEmail, new Date(created));
    return result;  
  }
  
  private static class studentDBOpenHelper extends SQLiteOpenHelper 
  {

	  public studentDBOpenHelper(Context context, String name,
	                          CursorFactory factory, int version) 
	  {
	    super(context, name, factory, version);
	  }

	  // SQL Statement to create a new database.
	  private static final String DATABASE_CREATE = "create table " + 
	    DATABASE_TABLE + " (" + 
	    KEY_ID + " integer primary key autoincrement, " +
	    KEY_CLASS_ID + " long, " +
	    KEY_STUDENT_FIRST_NAME + " text not null, " + 
	    KEY_STUDENT_LAST_NAME + " text not null, " +
	    KEY_GUARDIAN_NAME + " text, " +
	    KEY_GUARDIAN_PHONE + " text, " +
	    KEY_GUARDIAN_EMAIL + " text, " +
	    KEY_CREATION_DATE + " long);";

	  @Override
	  public void onCreate(SQLiteDatabase _db) 
	  {
	    _db.execSQL(DATABASE_CREATE);
	  }

	  @Override
	  public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) 
	  {
	    Log.w("StudentDBAdapter", "Upgrading from version " + 
	                           _oldVersion + " to " +
	                           _newVersion + ", which will destroy all old data");

	    // Drop the old table.
	    _db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
	    // Create a new one.
	    onCreate(_db);
	  }
	}
}